package cn.wolfcode.service.impl;

import cn.wolfcode.domain.AccountTransaction;
import cn.wolfcode.domain.OperateIntegralVo;
import cn.wolfcode.domain.UsableIntegral;
import cn.wolfcode.mapper.AccountTransactionMapper;
import cn.wolfcode.mapper.UsableIntegralMapper;
import cn.wolfcode.service.IUsableIntegralService;
import io.seata.rm.tcc.api.BusinessActionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

/**
 * Created by lanxw
 */
@Service
public class UsableIntegralServiceImpl implements IUsableIntegralService {
    @Autowired
    private UsableIntegralMapper usableIntegralMapper;
    @Autowired
    private AccountTransactionMapper accountTransactionMapper;

    @Override
    public Boolean pay(OperateIntegralVo vo) {
        int integral = usableIntegralMapper.decrIntegral(vo.getPhone(), vo.getValue());
        // > 0是扣减成功
        return integral > 0;
    }

    @Override
    public void refund(OperateIntegralVo vo) {
        usableIntegralMapper.incrIntegral(vo.getPhone(),vo.getValue());
    }

    @Override
    @Transactional
    public Boolean payTry(OperateIntegralVo vo, BusinessActionContext context) {
        System.out.println("积分try方法逻辑");
        // 执行业务逻辑(预资源，冻结用户对应要花费的积分数)
        int effectRows = usableIntegralMapper.freezeIntegral(vo.getPhone(), vo.getValue());
        // 不为0，插入事务日志
        if (effectRows > 0) {
            AccountTransaction transaction = new AccountTransaction();
            transaction.setTxId(context.getXid()); // 全局事务id
            transaction.setActionId(context.getBranchId()); //分支事务id
            transaction.setAmount(vo.getValue()); // 此次积分变更数值
            transaction.setGmtCreated(new Date()); //创建时间
            transaction.setGmtModified(new Date()); // 修改时间
            transaction.setPhone(vo.getPhone()); //手机号
            // transaction.setState(AccountTransaction.STATE_TRY); // 默认try操作
            accountTransactionMapper.insert(transaction);
        }
        //int effectRows = usableIntegralMapper.decrIntegral(vo.getPhone(), vo.getValue());
        // 写在这里的话，假如effectRows为0，那么返回的是false，那么秒杀那边的判断就会有异常，那么就会
        // 发起全局回滚，因为这里的日志表已经插进去了，这里分支事务的cancel就会以为积分已经减了，
        // 那么回滚事务的时候，会添加积分，从而积分变多了
        return effectRows>0;
    }

    @Override
    @Transactional
    public void payConfirm(BusinessActionContext context) {
        System.out.println("积分confirm方法逻辑");
        // 查询日志
        AccountTransaction transaction = accountTransactionMapper.get(context.getXid(), context.getBranchId());
        // 执行提交逻辑
        if (transaction != null) {
            // 幂等性操作判断，为了防止多次操作
            if (AccountTransaction.STATE_TRY == transaction.getState()) {
                // 修改事务日志状态为CONFIRM
                int effectRows = accountTransactionMapper.updateAccountTransactionState(context.getXid(), context.getBranchId(), AccountTransaction.STATE_COMMIT, AccountTransaction.STATE_TRY);
                if (effectRows > 0) {
                    // 修改冻结余额,真实扣除
                    usableIntegralMapper.commitChange(transaction.getPhone(),transaction.getAmount());
                }

            } else {
                // 可删掉else
                // 说明状态属于CONFIRM--->幂等处理

            }
        } else {
            // 一般不会为空的，过了try就是成功的了，可删掉else
            // 属于异常情况--->通知管理员处理
        }
    }

    @Override
    @Transactional
    public void payCancel(BusinessActionContext context) {
        System.out.println("积分cancel方法逻辑");
        // 查询事务日志
        AccountTransaction transaction = accountTransactionMapper.get(context.getXid(), context.getBranchId());
        if (transaction == null) {
            transaction = new AccountTransaction();
            // 说明是空回滚情况，需要插入日志，防止悬挂的情况
            transaction.setTxId(context.getXid());
            transaction.setActionId(context.getBranchId());
            transaction.setGmtCreated(new Date());
            transaction.setGmtModified(new Date());
            transaction.setState(AccountTransaction.STATE_TRY);
            accountTransactionMapper.insert(transaction);
        } else {
            // 如果不为空，进行cancel逻辑
            if (AccountTransaction.STATE_TRY == transaction.getState()) {
                int effectRows = accountTransactionMapper.updateAccountTransactionState(transaction.getTxId(), transaction.getActionId(), AccountTransaction.STATE_CANCEL, transaction.getState());
                if (effectRows > 0) {
                    // 回滚数据
                    usableIntegralMapper.unFreezeIntegral(transaction.getPhone(),transaction.getAmount());
                }
            }
        }
    }

    @Override
    @Transactional
    public Boolean refundTry(OperateIntegralVo vo, BusinessActionContext context) {
        System.out.println("积分try方法逻辑");
        // 执行预资源逻辑,冻结积分数
        int effectRows = usableIntegralMapper.commitChange(vo.getPhone(), -vo.getValue());
        if (effectRows > 0) {
            // 插入事务日志
            AccountTransaction transaction = new AccountTransaction();
            transaction.setTxId(context.getXid()); // 全局事务id
            transaction.setActionId(context.getBranchId()); //分支事务id
            transaction.setAmount(vo.getValue()); // 此次积分变更数值
            transaction.setGmtCreated(new Date()); //创建时间
            transaction.setGmtModified(new Date()); // 修改时间
            transaction.setPhone(vo.getPhone()); //手机号
            // transaction.setState(AccountTransaction.STATE_TRY); // 默认try操作
            accountTransactionMapper.insert(transaction);
        }
        return effectRows > 0;
    }

    @Override
    @Transactional
    public void refundConfirm(BusinessActionContext context) {
        System.out.println("积分confirm方法逻辑");
        // 查询事务日志
        AccountTransaction transaction = accountTransactionMapper.get(context.getXid(), context.getBranchId());
        if (transaction != null) {
            // 正常日志不会为空，除非人工删除了
            // 幂等性操作
            if (AccountTransaction.STATE_TRY == transaction.getState()) {
                // 执行提交操作
                // 事务日志的状态修改
                int effectRows = accountTransactionMapper.updateAccountTransactionState(transaction.getTxId(), transaction.getActionId(), AccountTransaction.STATE_COMMIT, transaction.getState());
                if (effectRows > 0) {
                    // 冻结积分数的取消
                    usableIntegralMapper.unFreezeIntegral(transaction.getPhone(),transaction.getAmount());
                }
            } else {

            }
        } else {

        }
    }

    @Override
    @Transactional
    public void refundCancel(BusinessActionContext context) {
        System.out.println("积分cancel方法逻辑");
        // 查询事务日志
        AccountTransaction transaction = accountTransactionMapper.get(context.getXid(), context.getBranchId());
        if (transaction == null) {
            transaction = new AccountTransaction();
            // 空回滚情况，插入日志，以防try悬挂资源，不让try执行方法成功
            transaction.setTxId(context.getXid());
            transaction.setActionId(context.getBranchId());
            transaction.setGmtCreated(new Date());
            transaction.setGmtModified(new Date());
            transaction.setState(AccountTransaction.STATE_TRY);
            accountTransactionMapper.insert(transaction);
        } else {
            // 不为空
            // 修改事务日志状态
            int effectRows = accountTransactionMapper.updateAccountTransactionState(context.getXid(), context.getBranchId(), AccountTransaction.STATE_CANCEL, transaction.getState());
            if (effectRows > 0) {
                // 取消冻结资源
                usableIntegralMapper.commitChange(transaction.getPhone(),transaction.getAmount());
            }
        }
    }
}
